<?php

namespace Shadon\CloudPrint;

/*
 * This file is part of blty package.
 *
 * (c) blty.com
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

use Shadon\CloudPrint\Configuration\Config;
use Shadon\CloudPrint\Exceptions\ConfigException;
use Shadon\CloudPrint\Gateways\Gateway;

class CloudPrint
{
    /**
     * @var \Shadon\CloudPrint\Configuration\Config
     */
    protected $config;

    /**
     * @var string
     */
    protected $gateway = '';

    /**
     * @var array
     */
    protected $gateways = [];

    /**
     * Constructor.
     *
     * @param array $config
     * @throws \Shadon\CloudPrint\Exceptions\ConfigException
     */
    public function __construct(array $config)
    {
        if(empty($config)){
            throw new ConfigException('配置不存在');
        }elseif(empty($config['gateway'])){
            throw new ConfigException('网关配置不存在');
        }
        $this->config = new Config($config);
        $this->setGateway($this->config['gateway']);
    }

    /**
     * Set gateway name.
     *
     * @param string $name
     *
     * @return $this
     */
    private function setGateway(string $name)
    {
        $this->gateway = $name;
        return $this;
    }

    /**
     * Get gateway name.
     *
     * @return string
     * @throws \Shadon\CloudPrint\Exceptions\ConfigException
     */
    public function getGateway()
    {
        if(empty($this->gateway)){
            throw new ConfigException('gateway not found');
        }
        return $this->gateway;
    }

    /**
     * Format gateway name.
     *
     * @param string $name
     *
     * @return string
     */
    protected function formatGatewayClassName(string $name)
    {
        if (\class_exists($name)) {
            return $name;
        }
        $name = \ucfirst(\str_replace(['-', '_', ''], '', $name));

        return __NAMESPACE__."\\Gateways\\{$name}Gateway";
    }

    /**
     * get gateway class
     *
     * @throws ConfigException
     */
    public function gateway()
    {
        $name = $this->getGateway();
        if(!isset($this->gateways[$name])){
            $this->gateways[$name] = $this->createGateway($name);
        }
        return $this->gateways[$name];
    }

    /**
     * Create a new driver class.
     *
     * @param string $name
     *
     * @return Gateway
     * @throws ConfigException
     */
    protected function createGateway(string $name)
    {
        if(isset($this->callCustomCreator[$name])){
            $gateway = $this->callCustomCreator($name);
        }else{
            $className = $this->formatGatewayClassName($name);
            $gateway = $this->makeGateway($className, $this->config);
        }
        return $gateway;
    }

    /**
     * Call a custom gateway creator.
     *
     * @param string $gateway
     *
     * @return mixed
     */
    protected function callCustomCreator(string $gateway)
    {
        return \call_user_func($this->customCreators[$gateway], $this->config);
    }

    /**
     * regist custom class
     *
     * @param string $name 网关名称
     * @param \Closure 匿名函数类
     * @return $this
     */
    protected  function registCustomClass(string $name, Closure $callback)
    {
        $this->customCreators[$name] = $callback;
        return $this;
    }

    /**
     * create gateway class
     *
     * @param string $gateway 网关名称
     * @param Config  $config
     *
     * @return Gateway
     *
     * @throws \Shadon\CloudPrint\Exceptions\ConfigException
     */
    protected function makeGateway(string $gateway, Config $config)
    {
        if (!\class_exists($gateway)) {
            throw new ConfigException("打印类:{$gateway}不存在");
        }
        return new $gateway($config);
    }
}